/*
 * Copyright 2015, gRPC Authors All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package keter.lab.grpc.client;

import io.grpc.*;
import keter.lab.grpc.proto.HelloReply;
import keter.lab.grpc.proto.HelloRequest;
import keter.lab.grpc.proto.HelloServiceGrpc;
import keter.lab.grpc.server.HelloWorldServer;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

/**
 * 
 * A simple client that requests a greeting from the {@link HelloWorldServer}.
 */
public class HelloWorldClient {
  private static final org.slf4j.Logger logger = LoggerFactory.getLogger(HelloWorldClient.class);

  private final ManagedChannel channel;
  private final HelloServiceGrpc.HelloServiceBlockingStub blockingStub;

  /** Construct client connecting to HelloWorld server at {@code host:port}. */
  public HelloWorldClient(String host, int port) {
    String token = "haha";
    ClientInterceptor interceptor = new HeaderClientInterceptor(token);
    channel = ManagedChannelBuilder.forAddress(host, port)
            .usePlaintext()
            .build();
    Channel channelWithHeader = ClientInterceptors.intercept(channel, interceptor);
//    this(channelWithHeader);
    blockingStub = HelloServiceGrpc.newBlockingStub(channelWithHeader);
  }

  /** Construct client for accessing RouteGuide server using the existing channel. */
  public HelloWorldClient(ManagedChannel channel) {
    this.channel = channel;
    blockingStub = HelloServiceGrpc.newBlockingStub(channel);
  }

  public void shutdown() throws InterruptedException {
    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
  }

  /** Say hello to server. */
  public String greet(String name) {
    logger.info("Will try to greet " + name + " ...");
    HelloRequest request = HelloRequest.newBuilder().setName(name).build();
    HelloReply response = null;
    try {
      response = blockingStub.sayHello(request);
      logger.info("Greeting: " + response.getMessage());

    } catch (StatusRuntimeException e) {
      logger.info("RPC failed: {0}", e.getStatus());
    }
    return response.getMessage();
  }

  public void listHaha(String name) throws InterruptedException {
    logger.info("Will try to greet " + name + " ...");
    HelloRequest request = HelloRequest.newBuilder().setName(name).build();
    final Iterator<HelloReply> response;
    try {
      response = blockingStub.listHaha(request);
      while(response.hasNext()){
          logger.info("message is: " + response.next().getMessage());
      }

    } catch (Exception e) {
      if(e instanceof StatusRuntimeException) {
        StatusRuntimeException sre = (StatusRuntimeException) e;
        logger.info("RPC failed: {0}", sre.getStatus());
        logger.info("输入任意内容后，将进行重连...");
        String line = new Scanner(System.in).nextLine();
        initClient(new String[0]);
      }
    }
  }

  /**
   * Greet server. If provided, the first element of {@code args} is the name to use in the
   * greeting.
   */
  public static void main(String[] args) throws Exception {
    initClient(args);
  }

  private static void initClient(String[] args) throws InterruptedException {
    HelloWorldClient client = new HelloWorldClient("127.0.0.1", 50051);
    try {
      /* Access a service running on the local machine on port 50051 */
      String user = "world";
      if (args!=null && args.length > 0) {
        user = args[0]; /* Use the arg as the name to greet if provided */
      }
        client.greet(user);
        Thread.sleep(2000);
        logger.info("流式输出模拟。。");
        client.listHaha("haha");
    } finally {
      client.shutdown();
    }
  }
}
